作者:一啖过 | 来源:互联网 | 2023-09-24 12:57
前面主要分析ThreadPoolExecutor类的创建和运行过程,今天学习Executors类。1.Executors类和Executor类的关系Executo
前面主要分析ThreadPoolExecutor类的创建和运行过程,今天学习Executors类。
1.Executors类和Executor类的关系 Executor是含有执行提交Runnable任务的接口。如果你看了关于ThreadPoolExecutor类的分析,那么就知道线程池间接实现Executor接口。 Executors是一个工厂类,它能提供各种形式的线程池。 2.Executors类的作用 创建以下线程池和执行器。
2.1 newFixedThreadPool 创建一个线程池,该线程池重用在共享无界队列上运行的固定数量的线程。在任何时候,大多数nThreads线程都是活动的处理任务。如果在所有线程都处于活动状态时提交其他任务,它们将在队列中等待,直到线程可用为止。如果任何线程在关闭之前的执行过程中由于失败而终止,那么如果需要执行后续任务,则会替换一个新线程。池中的线程将一直存在,直到显式地执行execuorservice #shutdown关机。
public static ExecutorService newFixedThreadPool ( int nThreads) { return new ThreadPoolExecutor ( nThreads, nThreads, 0 L, TimeUnit. MILLISECONDS, new LinkedBlockingQueue < Runnable> ( ) ) ; } public static ExecutorService newFixedThreadPool ( int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor ( nThreads, nThreads, 0 L, TimeUnit. MILLISECONDS, new LinkedBlockingQueue < Runnable> ( ) , threadFactory) ; }
注意看到核心线程数和最大线程数都为nThreads&#xff0c;表明线程池内自始至终可用线程数为nThread&#xff1b;如果线程池内线程数已经达到nThreads&#xff0c;那么新到达的Runnable任务直接放入等待队列&#xff0c;由于不会再新建线程&#xff0c;所以为了保证池的可用性就使用无界等待队列。 注意提供重载的方法&#xff0c;提供自定义的线程工厂。
2.2 newCachedThreadPool 创建一个线程池&#xff0c;该线程池根据需要创建新线程&#xff0c;但在可用时将重用以前构造的线程。这些池通常会提高执行许多短期异步任务的程序的性能。如果可用&#xff0c;要执行的调用将重用以前构造的线程。如果没有可用的现有线程&#xff0c;将创建一个新线程并将其添加到池中。未使用60秒的线程将被终止并从缓存中删除。因此&#xff0c;长时间空闲的池不会消耗任何资源。注意&#xff0c;可以使用ThreadPoolExecutor构造函数创建具有相似属性但不同细节(例如超时参数)的池。
public static ExecutorService newCachedThreadPool ( ) { return new ThreadPoolExecutor ( 0 , Integer. MAX_VALUE, 60 L, TimeUnit. SECONDS, new SynchronousQueue < Runnable> ( ) ) ; } public static ExecutorService newCachedThreadPool ( ThreadFactory threadFactory) { return new ThreadPoolExecutor ( 0 , Integer. MAX_VALUE, 60 L, TimeUnit. SECONDS, new SynchronousQueue < Runnable> ( ) , threadFactory) ; }
注意该线程池核心线程数为0&#xff0c;最大线程池数为2^32-1&#xff0c;空闲线程只存活60秒&#xff1b;等待队列并不能存储Runnable任务&#xff0c;反而使得线程池继续创建线程来执行任务。
2.3 newScheduledThreadPool 创建一个线程池&#xff0c;该线程池可以调度在给定延迟之后运行的命令&#xff0c;或者定期执行命令。
public static ScheduledExecutorService newScheduledThreadPool ( int corePoolSize) { return new ScheduledThreadPoolExecutor ( corePoolSize) ; } public static ScheduledExecutorService newScheduledThreadPool ( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor ( corePoolSize, threadFactory) ; }
注意该线程池调用ScheduledThreadPoolExecutor类的构造方法。
2.4 newSingleThreadExecutor 创建一个执行器&#xff0c;该执行器使用一个工作线程操作一个无界队列。(但是请注意&#xff0c;如果这个线程在关闭之前的执行过程中由于失败而终止&#xff0c;那么如果需要执行后续任务&#xff0c;将会有一个新的线程替代它。)任务保证按顺序执行&#xff0c;并且在任何给定时间都不会有多个任务处于活动状态。与其他等价的newFixedThreadPool(1)不同&#xff0c;返回的执行器保证不可重新配置以使用其他线程。
public static ExecutorService newSingleThreadExecutor ( ) { return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor ( 1 , 1 , 0 L, TimeUnit. MILLISECONDS, new LinkedBlockingQueue < Runnable> ( ) ) ) ; } public static ExecutorService newSingleThreadExecutor ( ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor ( 1 , 1 , 0 L, TimeUnit. MILLISECONDS, new LinkedBlockingQueue < Runnable> ( ) , threadFactory) ) ; }
此刻我们注意到FinalizableDelegatedExecutorService包装ThreadPoolExecutor对象&#xff0c;其实FinalizableDelegatedExecutorService继承自DelegatedExecutorService&#xff0c;该类是只公开ExecutorService实现的ExecutorService方法的包装器类。
2.5 newSingleThreadScheduledExecutor 创建一个单线程执行器&#xff0c;该执行器可以安排命令在给定的延迟之后运行&#xff0c;或者定期执行。(但是请注意&#xff0c;如果这个线程在关闭之前的执行过程中由于失败而终止&#xff0c;那么如果需要执行后续任务&#xff0c;将会有一个新的线程替代它。)任务保证按顺序执行&#xff0c;并且在任何给定时间都不会有多个任务处于活动状态。与其他等价的newScheduledThreadPool(1)不同&#xff0c;返回的执行器保证不可重新配置以使用其他线程。
public static ScheduledExecutorService newSingleThreadScheduledExecutor ( ) { return new DelegatedScheduledExecutorService ( new ScheduledThreadPoolExecutor ( 1 ) ) ; } public static ScheduledExecutorService newSingleThreadScheduledExecutor ( ThreadFactory threadFactory) { return new DelegatedScheduledExecutorService ( new ScheduledThreadPoolExecutor ( 1 , threadFactory) ) ; }
提供两种线程工厂
DefaultThreadFactory&#xff1a;默认的线程工厂 static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber &#61; new AtomicInteger ( 1 ) ; private final ThreadGroup group; private final AtomicInteger threadNumber &#61; new AtomicInteger ( 1 ) ; private final String namePrefix; DefaultThreadFactory ( ) { SecurityManager s &#61; System. getSecurityManager ( ) ; group &#61; ( s !&#61; null) ? s. getThreadGroup ( ) : Thread. currentThread ( ) . getThreadGroup ( ) ; namePrefix &#61; "pool-" &#43; poolNumber. getAndIncrement ( ) &#43; "-thread-" ; } public Thread newThread ( Runnable r) { Thread t &#61; new Thread ( group, r, namePrefix &#43; threadNumber. getAndIncrement ( ) , 0 ) ; if ( t. isDaemon ( ) ) t. setDaemon ( false ) ; if ( t. getPriority ( ) !&#61; Thread. NORM_PRIORITY) t. setPriority ( Thread. NORM_PRIORITY) ; return t; } }
默认的线程工厂通过newThread(Runnable)方法创建新的线程。并确定新线程的线程组&#xff0c;默认名字(格式&#xff1a;pool-poolNumber-thread-threadNumber)&#xff1b;设置为非守护线程&#xff0c;便于销毁&#xff1b;设置新线程的优先级。
PrivilegedThreadFactory&#xff1a;享有特权的线程工厂。 它可以捕获访问控制上下文acc和类加载器ccl。 static class PrivilegedThreadFactory extends DefaultThreadFactory { private final AccessControlContext acc; private final ClassLoader ccl; PrivilegedThreadFactory ( ) { super ( ) ; SecurityManager sm &#61; System. getSecurityManager ( ) ; if ( sm !&#61; null) { sm. checkPermission ( SecurityConstants. GET_CLASSLOADER_PERMISSION) ; sm. checkPermission ( new RuntimePermission ( "setContextClassLoader" ) ) ; } this . acc &#61; AccessController. getContext ( ) ; this . ccl &#61; Thread. currentThread ( ) . getContextClassLoader ( ) ; } public Thread newThread ( final Runnable r) { return super . newThread ( new Runnable ( ) { public void run ( ) { AccessController. doPrivileged ( new PrivilegedAction < Void> ( ) { public Void run ( ) { Thread. currentThread ( ) . setContextClassLoader ( ccl) ; r. run ( ) ; return null; } } , acc) ; } } ) ; } }
在创建新线程的时候设置当前线程的控制上下文和类加载器与调用该线程工厂的线程的控制上下文和类加载器一致。